package v1

import (
	"strconv"
	"yuanxin-admin/internal/common/ioc"
	"yuanxin-admin/internal/dto"
	"yuanxin-admin/internal/model"
	"yuanxin-admin/internal/repository"
	"yuanxin-admin/internal/service"
	"yuanxin-admin/internal/vo"

	"gitee.com/botaoshow/yuanxin/web/common/database"
	"gitee.com/botaoshow/yuanxin/web/response"
	"gitee.com/botaoshow/yuanxin/web/utils/pages"
	"github.com/gin-gonic/gin"
)

type SysDictController struct {
	sysDictService service.ISysDictService
}

func NewSysDictController() *SysDictController {
	return &SysDictController{
		sysDictService: ioc.Inject[service.ISysDictService]((service.ISysDictService)(nil)),
	}
}

func (s *SysDictController) QueryPage(c *gin.Context) {
	name := c.DefaultQuery("name", "")
	code := c.DefaultQuery("code", "")
	type0 := c.DefaultQuery("type", "")
	status := c.DefaultQuery("status", "")
	var pg pages.PageDTO
	err := c.ShouldBind(&pg)
	if err != nil {
		response.Fail(c, err.Error())
		return
	}
	offset, limit := pages.GetOffsetAndLimitByPageDTO(&pg)
	q := repository.SysDict.WithContext(c)
	if name != "" {
		q = q.Where(repository.SysDict.Name.Eq(name))
	}
	if code != "" {
		q = q.Where(repository.SysDict.Code.Eq(code))
	}
	if type0 != "" {
		q = q.Where(repository.SysDict.Type.Eq(type0))
	}
	if status != "" {
		q = q.Where(repository.SysDict.Status.Eq(status))
	}
	result, count, err := q.FindByPage(offset, limit)
	if err != nil {
		response.Fail(c, err.Error())
		return
	}
	page := pages.NewPage(result, count, pg.PageNum, pg.PageSize)
	response.Success(c, page)
}

func (s *SysDictController) Query(c *gin.Context) {
	code := c.Param("code")
	d, err := repository.SysDict.WithContext(c).Select(repository.SysDict.ID, repository.SysDict.Type).
		Where(repository.SysDict.Code.Eq(code)).First()
	if err != nil {
		response.Fail(c, err.Error())
		return
	}
	if d == nil {
		response.Fail(c, "字典不存在")
		return
	}
	id := d.ID
	if "list" == d.Type {
		var list []*model.SysDictOption
		err := repository.SysDictOption.WithContext(c).
			Where(repository.SysDictOption.TypeID.Eq(id)).
			Order(repository.SysDictOption.Sort.Asc()).
			Scan(&list)
		if err != nil {
			response.Fail(c, err.Error())
			return
		}
		response.Success(c, list)
		return
	}
	if "tree" == d.Type {
		var list []*model.SysDictOption
		err := repository.SysDictOption.WithContext(c).
			Where(repository.SysDictOption.TypeID.Eq(id)).
			Order(repository.SysDictOption.Sort.Asc()).
			Scan(&list)
		if err != nil {
			response.Fail(c, err.Error())
			return
		}
		if list == nil || len(list) == 0 {
			list = []*model.SysDictOption{}
			response.Success(c, list)
			return
		}
		sub := queryTreeDataSub(list, nil)
		response.Success(c, sub)
		return
	}

}

// queryTreeDataSub 递归查询树形数据
func queryTreeDataSub(list []*model.SysDictOption, pid *int64) []*vo.SysDictTreeOptionVO {
	var listVO = make([]*vo.SysDictTreeOptionVO, 0)
	for _, v := range list {
		// 正确判断父子关系
		isMatch := (pid == nil && v.ParentID == nil) ||
			(pid != nil && v.ParentID != nil && *v.ParentID == *pid)

		if isMatch {
			node := &vo.SysDictTreeOptionVO{
				Id:       v.ID,
				TypeId:   v.TypeID,
				Label:    v.Label,
				Value:    v.Value,
				ParentId: v.ParentID,
				Status:   v.Status,
				Sort:     v.Sort,
				Children: make([]*vo.SysDictTreeOptionVO, 0), // 先初始化为空切片
			}
			// 递归查找子节点
			node.Children = queryTreeDataSub(list, &v.ID)
			listVO = append(listVO, node)
		}
	}
	return listVO
}
func (s *SysDictController) QueryListData(c *gin.Context) {
	id := c.Param("id")
	id0, _ := strconv.Atoi(id)
	list, err := repository.SysDictOption.WithContext(c).
		Where(repository.SysDictOption.TypeID.Eq(int64(id0))).
		Order(repository.SysDictOption.Sort.Asc()).
		Find()
	if err != nil {
		response.Fail(c, err.Error())
		return
	}
	response.Success(c, list)
}

func (s *SysDictController) QueryTreeData(c *gin.Context) {
	id0, _ := strconv.Atoi(c.Param("id"))
	id := int64(id0)
	var list []*model.SysDictOption
	err := repository.SysDictOption.WithContext(c).
		Where(repository.SysDictOption.TypeID.Eq(id)).
		Order(repository.SysDictOption.Sort.Asc()).
		Scan(&list)
	if err != nil {
		response.Fail(c, err.Error())
		return
	}
	if list == nil || len(list) == 0 {
		list = []*model.SysDictOption{}
		response.Success(c, list)
		return
	}
	sub := queryTreeDataSub(list, nil)
	response.Success(c, sub)
}

func (s *SysDictController) Create(c *gin.Context) {
	var d dto.SysDictDTO
	if err := c.ShouldBind(&d); err != nil {
		response.Fail(c, err.Error())
		return
	}
	b, err := s.sysDictService.Create(c, &d)
	if err != nil {
		response.Fail(c, err.Error())
		return
	}
	response.ToAjax(c, b)
}

func (s *SysDictController) Update(c *gin.Context) {
	var d dto.SysDictDTO
	if err := c.ShouldBind(&d); err != nil {
		response.Fail(c, err.Error())
		return
	}
	id0, _ := strconv.Atoi(c.Param("id"))
	id := int64(id0)
	b, err := s.sysDictService.Update(c, id, &d)
	if err != nil {
		response.Fail(c, err.Error())
		return
	}
	response.ToAjax(c, b)
}
func (s *SysDictController) Delete(c *gin.Context) {
	id0, _ := strconv.Atoi(c.Param("id"))
	id := int64(id0)
	q := repository.Use(database.Db)
	err := q.Transaction(func(tx *repository.Query) error {
		// 使用gen方式删除，确保错误能正确捕获
		if _, err := tx.SysDictOption.WithContext(c).Where(tx.SysDictOption.TypeID.Eq(id)).Delete(); err != nil {
			return err
		}
		if _, err := tx.SysDict.WithContext(c).Where(tx.SysDict.ID.Eq(id)).Delete(); err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		response.Fail(c, err.Error())
		return
	}
	response.SuccessDefault(c)
}
func (s *SysDictController) OptionCreate(c *gin.Context) {
	var d dto.SysDictOptionDTO
	if err := c.ShouldBind(&d); err != nil {
		response.Fail(c, err.Error())
		return
	}
	entity := d.ToEntity()
	if err := repository.SysDictOption.WithContext(c).Create(entity); err != nil {
		response.Fail(c, err.Error())
		return
	} else {
		response.SuccessDefault(c)
	}
}
func (s *SysDictController) OptionUpdate(c *gin.Context) {
	id := c.Param("id")
	id0, _ := strconv.Atoi(id)
	var d dto.SysDictOptionDTO
	if err := c.ShouldBind(&d); err != nil {
		response.Fail(c, err.Error())
		return
	}
	entity := d.ToEntity()
	entity.ID = int64(id0)
	if b, err := repository.SysDictOption.WithContext(c).
		Where(repository.SysDictOption.ID.Eq(int64(id0))).
		Updates(entity); err != nil {
		response.Fail(c, err.Error())
		return
	} else {
		response.ToAjax(c, b.RowsAffected > 0)

	}
}
func (s *SysDictController) OptionDelete(c *gin.Context) {
	id := c.Param("id")
	id0, _ := strconv.Atoi(id)
	if b, err := repository.SysDictOption.WithContext(c).Where(repository.SysDictOption.ID.Eq(int64(id0))).Delete(); err != nil {
		response.Fail(c, err.Error())
	} else {
		response.ToAjax(c, b.RowsAffected > 0)
	}

}
